#pragma once
#include <Rz/Object.h>
#include <Rz/Collections/List.h>
#include <Rz/Graphics/Render/VertexDescriptions/IVertexDescription.h>
#include "Geometry.h"
#include "IRenderDevice.h"
#include "../Math/BoundingBox.h"

namespace Rz { namespace Graphics { namespace Render {

template <typename T>
class GeometryBuilder :
	public Object
{
	public:
		RZ_RTTI(Rz::Graphics::Render, GeometryBuilder);
		RZ_RTTI_IMPLEMENTS(Object);
		RZ_RTTI_TEMPLATES(T);
		RZ_RTTI_END;

		RZ_IMPLEMENTS(VertexDescriptions::IVertexDescription, T);

		GeometryBuilder(IRenderDevice* renderDevice);

		void AddQuad(const T& v1, const T& v2, const T& v3, const T& v4);
		void AddTriangle(const T& v1, const T& v2, const T& v3);

		u32 AddVertex(const T& vertex);
		
		void AddFace3(u32 i1, u32 i2, u32 i3);
		void AddFace4(u32 i1, u32 i2, u32 i3, u32 i4);

		void Clear();

		void CalculateNormals();
		void SmoothNormals();

		void CalculateBoundingBox();

		T& operator [] (u32 index);
		const T& operator [] (u32 index) const;

		u32 GetVertexCount() const;
		u32 GetIndexCount() const;

		Geometry* ToGeometry();

	protected:
		void MakeRawBuffer();

	private:
		Ptr<IRenderDevice> _renderDevice;

		Collections::List<f32>	_rawVertices;
		Collections::List<T>	_vertices;
		Collections::List<u32>	_indices;

		Math::BoundingBox _boundingBox;
};

} } }

#include "GeometryBuilder.inl"
